package com.wzb.mybatisplus.bitaction.electrumaction;

import javax.net.ssl.*;
import java.io.*;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.List;

public class CertificateManager {

    private static final String CERT_DIR = "./electrum-certs/";
    private static final String KEYSTORE_PASSWORD = "changeit";

    /**
     * 下载Electrum服务器证书
     */
    public static File downloadCertificate(String host, int port) throws Exception {
        // 创建证书目录
        File certDir = new File(CERT_DIR);
        if (!certDir.exists()) {
            certDir.mkdirs();
        }

        File certFile = new File(CERT_DIR + host + ".crt");

        if (certFile.exists()) {
            System.out.println("使用现有证书: " + certFile.getAbsolutePath());
            return certFile;
        }

        System.out.println("下载证书: " + host + ":" + port);

        // 方法1: 使用Java原生方式获取证书
        try {
            SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
            try (SSLSocket socket = (SSLSocket) factory.createSocket(host, port)) {
                socket.startHandshake();

                SSLSession session = socket.getSession();
                java.security.cert.Certificate[] serverCerts = session.getPeerCertificates();

                if (serverCerts.length > 0) {
                    try (FileOutputStream fos = new FileOutputStream(certFile)) {
                        fos.write(serverCerts[0].getEncoded());
                    }
                    System.out.println("证书下载成功: " + certFile.getAbsolutePath());
                    return certFile;
                }
            }
        } catch (Exception e) {
            System.out.println("Java方式下载失败: " + e.getMessage());
        }

        // 方法2: 使用外部openssl命令
        return downloadWithOpenSSL(host, port, certFile);
    }

    /**
     * 使用openssl下载证书
     */
    private static File downloadWithOpenSSL(String host, int port, File certFile) throws Exception {
        try {
            ProcessBuilder pb = new ProcessBuilder(
                    "openssl", "s_client", "-connect", host + ":" + port,
                    "-showcerts"
            );

            Process process = pb.start();

            // 向进程发送空输入并等待结束
            try (OutputStream os = process.getOutputStream()) {
                os.write("\n".getBytes());
                os.flush();
            }

            // 读取输出
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            StringBuilder certificateData = new StringBuilder();
            String line;
            boolean inCertificate = false;
            int certCount = 0;

            while ((line = reader.readLine()) != null) {
                if (line.contains("BEGIN CERTIFICATE")) {
                    inCertificate = true;
                    certCount++;
                }
                if (inCertificate) {
                    certificateData.append(line).append("\n");
                }
                if (line.contains("END CERTIFICATE")) {
                    inCertificate = false;
                    // 只保存第一个证书（服务器证书）
                    if (certCount == 1) {
                        break;
                    }
                }
            }

            process.waitFor();

            if (certificateData.length() > 0) {
                try (FileWriter writer = new FileWriter(certFile)) {
                    writer.write(certificateData.toString());
                }
                System.out.println("OpenSSL证书下载成功: " + certFile.getAbsolutePath());
                return certFile;
            }

        } catch (Exception e) {
            System.out.println("OpenSSL方式下载失败: " + e.getMessage());
        }

        throw new RuntimeException("无法下载证书: " + host);
    }

    /**
     * 导入证书到Java信任库
     */
    public static void importToJavaTrustStore(File certFile, String alias) throws Exception {
        String javaHome = System.getProperty("java.home");
        String cacertsPath = javaHome + File.separator + "lib" + File.separator + "security" + File.separator + "cacerts";

        System.out.println("导入证书到: " + cacertsPath);
        System.out.println("证书别名: " + alias);

        File cacertsFile = new File(cacertsPath);
        if (!cacertsFile.exists()) {
            throw new FileNotFoundException("信任库文件不存在: " + cacertsPath);
        }

        // 加载证书
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        Certificate cert;
        try (FileInputStream certFis = new FileInputStream(certFile)) {
            cert = cf.generateCertificate(certFis);
        }

        // 加载现有信任库
        KeyStore keystore;
        try (FileInputStream keystoreFis = new FileInputStream(cacertsPath)) {
            keystore = KeyStore.getInstance(KeyStore.getDefaultType());
            keystore.load(keystoreFis, KEYSTORE_PASSWORD.toCharArray());
        }

        // 添加证书
        keystore.setCertificateEntry(alias, cert);

        // 保存信任库
        try (FileOutputStream keystoreFos = new FileOutputStream(cacertsPath)) {
            keystore.store(keystoreFos, KEYSTORE_PASSWORD.toCharArray());
        }

        System.out.println("✓ 证书导入成功");
    }

    /**
     * 创建包含自定义证书的SSLContext
     */
    public static SSLContext createCustomSSLContext(File certFile) throws Exception {
        // 加载证书
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        Certificate ca;
        try (FileInputStream fis = new FileInputStream(certFile)) {
            ca = cf.generateCertificate(fis);
        }

        // 创建KeyStore
        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
        keyStore.load(null, null);
        keyStore.setCertificateEntry("electrum-ca", ca);

        // 创建TrustManager
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init(keyStore);

        // 创建SSLContext
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, tmf.getTrustManagers(), null);

        return sslContext;
    }

    /**
     * 检查证书是否已存在
     */
    public static boolean isCertificateInstalled(String alias) {
        try {
            String javaHome = System.getProperty("java.home");
            String cacertsPath = javaHome + File.separator + "lib" + File.separator + "security" + File.separator + "cacerts";

            KeyStore keystore;
            try (FileInputStream fis = new FileInputStream(cacertsPath)) {
                keystore = KeyStore.getInstance(KeyStore.getDefaultType());
                keystore.load(fis, KEYSTORE_PASSWORD.toCharArray());
            }

            return keystore.containsAlias(alias);
        } catch (Exception e) {
            return false;
        }
    }
}